{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "30d451ba-68b9-400f-a724-83c43caebfeb",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Getting started\n",
    "\n",
    "\n",
    "Welcome to hvPlot!\n",
    "\n",
    "This getting started guide will get you set up with hvPlot and provide a basic overview of its features and strengths.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f9962dd-4aa6-4088-b7da-0c81a91f739b",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Installation\n",
    "\n",
    "\n",
    "hvPlot supports Python 3.10 and above on Linux, Windows, or Mac. You can install hvPlot via the following options:\n",
    "\n",
    "\n",
    "::::{tab-set}\n",
    "\n",
    ":::{tab-item} pip\n",
    "```bash\n",
    "pip install hvplot\n",
    "```\n",
    ":::\n",
    "\n",
    ":::{tab-item} conda\n",
    "```bash\n",
    "conda install conda-forge::hvplot\n",
    "```\n",
    ":::\n",
    "\n",
    ":::{tab-item} uv\n",
    "```bash\n",
    "uv pip install hvplot\n",
    "```\n",
    ":::\n",
    "\n",
    ":::{tab-item} other\n",
    "[Installing for development](../developer_guide.md)\n",
    "\n",
    ":::\n",
    "\n",
    "::::"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03f88ad3-7112-4a91-b350-64650988e234",
   "metadata": {
    "tags": []
   },
   "source": [
    "To run the guides in this site locally, create an environment with the required dependencies:\n",
    "\n",
    "```bash\n",
    "conda create -n hvplot-env -c conda-forge --override-channels hvplot geoviews datashader xarray pandas geopandas dask streamz networkx intake intake-xarray intake-parquet s3fs scipy spatialpandas pooch rasterio fiona plotly matplotlib hvsampledata jupyterlab\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3554be44-81cc-4942-85ce-166119b41517",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Overview\n",
    "\n",
    "The core functionality provided by hvPlot is a **simple and high-level plotting interface** (API), modeled on [Pandas](https://pandas.pydata.org)'s `.plot` API and extended in various ways leveraging capabilities offered by the packages of the [HoloViz](https://holoviz.org) ecosystem, most notably [HoloViews](https://holoviews.org/). hvPlot can generate interactive plots with either [Bokeh](https://bokeh.org) (default) or [Plotly](https://plotly.com/python/), or static plots with [Matplotlib](https://matplotlib.org). hvPlot supports many data libraries of the Python ecosystem such as `pandas`, `xarray`, `dask` etc."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fb9229d-dfce-4d91-99bc-529ce999244d",
   "metadata": {},
   "source": [
    "```{image} ../assets/diagram.svg\n",
    "---\n",
    "alt: hvPlot diagram\n",
    "align: center\n",
    "width: 80%\n",
    "---\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eee1d197-112f-4012-9451-b1685a542798",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Register `.hvplot`\n",
    "\n",
    "Let’s create a simple Pandas DataFrame we’ll plot later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9a31e0c-c7e5-40a8-86f1-e14d2a12d17c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1bd84ab5-2054-4ec6-ae6c-74037c7744c7",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "np.random.seed(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18ba0419-86e3-479d-9224-5d3ce7bbdb35",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "idx = pd.date_range('1/1/2000', periods=1000)\n",
    "df = pd.DataFrame(np.random.randn(1000, 4), index=idx, columns=list('ABCD')).cumsum()\n",
    "df.head(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95adfc83-7b39-463b-80a8-bcd801563146",
   "metadata": {
    "tags": []
   },
   "source": [
    "The most convenient way to use hvPlot is to register the `.hvplot` *accessor* on the data type you are working with. This is done with a special import of the form `import hvplot.<data library>`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ebaff587-72d8-48be-8c77-47e7f40c37d6",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import hvplot.pandas  # noqa"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1788969d-0b81-4cf0-b53a-594cc3f0aa63",
   "metadata": {},
   "source": [
    "In addition to registering the `.hvplot` accessor on Pandas objects, the import above sets the Bokeh plotting library as the default one and loads its corresponding extension.\n",
    "\n",
    ":::{attention}\n",
    "In a notebook, loading the extension means that there's actually some front-end code that is injected in the cell output of the import, this code being required for HoloViews plots to behave correctly. So make sure not to remove this cell!\n",
    ":::\n",
    "\n",
    "Now simply call `.hvplot()` on the DataFrame as you would call Pandas' `.plot()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc71994c-52ec-46d1-a220-c6ad6c1ecb21",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "first_plot = df.hvplot()\n",
    "first_plot"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e587cdf0-28d0-498d-bd75-4feabd9eb262",
   "metadata": {},
   "source": [
    "The same process can be applied to other libraries, we'll just show another example with Xarray."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e5e56c31-2138-406c-8424-a6e78765fb04",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import hvplot.xarray  # noqa\n",
    "\n",
    "air_ds = hvplot.sampledata.air_temperature(\"xarray\")\n",
    "air_ds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bba66d7a-e6e9-4ac3-bad9-d46ffcbea82d",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "air_ds.hvplot.image(data_aspect=1, frame_width=400, dynamic=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e6c5704-7fe8-4857-bcde-572279bfa819",
   "metadata": {
    "tags": []
   },
   "source": [
    "The default plots hvPlot generate are Bokeh plots. These plots are interactive and support panning, zooming, hovering, and clickable/selectable legends. It's worth spending some time getting used to interacting with this kind of plot."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "740bc606-0e4c-49f5-9c88-8ed8a09446c9",
   "metadata": {
    "tags": []
   },
   "source": [
    "## hvplot namespace\n",
    "\n",
    "The `.hvplot` namespace holds the range of supported plot methods (e.g. `line`, `scatter`, `hist`, etc.). Use tab completion in a notebook to explore the available plot types.\n",
    "\n",
    "```python\n",
    "df.hvplot.<TAB>\n",
    "```\n",
    "\n",
    "Similarly to Panda's API, every plot method accepts a wide range of parameters. You can explore them by calling `hvplot.help('line')` or using tab completion:\n",
    "\n",
    "```python\n",
    "df.hvplot.line(<TAB>\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bfd800f5-fc0a-4404-a749-4e2b58f62bb1",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Compose plots\n",
    "\n",
    "The object returned by an `.hvplot()` call is a [HoloViews](https://holoviews.org/index.html) object whose `repr` includes the HoloViews element type (e.g. `Curve`) and the dimensions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b4e0d40-0ae9-41d6-94c0-90309bb04d13",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "plot1 = df['A'].hvplot.area(alpha=0.2, color='red', height=150, responsive=True)\n",
    "plot2 = df['B'].hvplot.line(height=150, responsive=True)\n",
    "print(type(plot2))\n",
    "print(plot2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "88d3608a-79a6-4741-a24b-4703e0f8723f",
   "metadata": {
    "tags": []
   },
   "source": [
    "`HoloViews` objects can be easily composed using the `+` and `*` operators:\n",
    "\n",
    "- `<plot1> + <plot2>` lays the plots out in a *row* container\n",
    "- `(<plot1> + <plot2>).cols(1)` lays the plots out in a *column* container\n",
    "- `<plot1> * <plot2>` overlays the plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4ff9c02-536b-4c4b-98a8-b24e9855d5ad",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "plot1 + plot2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac816ded-94c9-44e8-84d9-8c24e1c49039",
   "metadata": {},
   "outputs": [],
   "source": [
    "(plot1 + plot2).cols(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd119e66-adb2-473d-8867-ce61ee1ec351",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot1 * plot2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75cfb3cb-db2c-4467-8b6a-d1218b3fb035",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Widgets-based exploration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "905d2767-6e9b-43fe-86d6-a347166db07e",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "df_penguins = hvplot.sampledata.penguins(\"pandas\")\n",
    "df_penguins.head(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c19c726c-9924-4b74-8fbe-72b6a65c5ca8",
   "metadata": {},
   "source": [
    "The `groupby` parameter allows us to declare which dimension(s) of the dataset we would like to make explorable with widgets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bafff17b-ccdd-40cc-ada2-3bad01e24e99",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "df_penguins.hvplot.scatter(\n",
    "    x='bill_length_mm', y='bill_depth_mm', groupby=['island', 'sex'],\n",
    "    height=300, width=400, dynamic=False,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7ab849e-5720-4713-8c9c-158a90097f2a",
   "metadata": {},
   "source": [
    "## Display large data\n",
    "\n",
    "hvPlot provides multiple ways to display arbitrarily large datasets. The most versatile option depends on [Datashader](https://datashader.org/) (optional dependency) and simply consists of setting `rasterize=True`. The plot returned is an image, each pixel of that image being colorized based on the number of points it contains; which means that all the points contribute to the image. This plot is also dynamic, zooming in and out and panning leads to a recomputation of the image. Luckily, this all happens really fast! The plot below is generated with no less than 5 million points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a444f5ec-7bb8-476b-a12f-5f77959cb3aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "NUM = 1_000_000\n",
    "dists = [\n",
    "    pd.DataFrame(dict(x=np.random.normal(x, s, NUM), y=np.random.normal(y, s, NUM)))\n",
    "     for x,  y,    s in [\n",
    "       ( 5,  2, 0.20),\n",
    "       ( 2, -4, 0.10),\n",
    "       (-2, -3, 0.50),\n",
    "       (-5,  2, 1.00),\n",
    "       ( 0,  0, 3.00)]\n",
    "]\n",
    "df_large_data = pd.concat(dists, ignore_index=True)\n",
    "print(len(df_large_data))\n",
    "df_large_data.head(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b679acc-548d-436b-a28c-986726f799a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_large_data.hvplot.points(\n",
    "    'x', 'y', rasterize=True, cnorm='eq_hist',\n",
    "    data_aspect=1, colorbar=False\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "675984b5-b0a4-4ff2-bf4b-bc2cd51ff071",
   "metadata": {
    "tags": []
   },
   "source": [
    ":::{note}\n",
    "This interactive functionality requires a live Python process to be running.\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3565051b-bdef-4a77-9a53-0313317c3218",
   "metadata": {},
   "source": [
    "## Geographic plots\n",
    "\n",
    "hvPlot can generate geographic plots and handle geospatial data (e.g., GeoPandas DataFrame) on its own."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c226b5d7-8608-4998-b34a-064f7b21135c",
   "metadata": {},
   "source": [
    "### Without GeoViews\n",
    "\n",
    "hvPlot allows us to add a tile map as a basemap to a plot with the `tiles` parameter without having to install [GeoViews](https://geoviews.org/). This is possible because hvPlot projects lat/lon values to easting/northing (EPSG:4326 to EPSG:3857) coordinates without additional package dependencies if it detects that the values falls within expected lat/lon ranges."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9055995-6227-446e-adcc-a6b98110a741",
   "metadata": {},
   "outputs": [],
   "source": [
    "earthquakes = hvplot.sampledata.earthquakes(\"pandas\")\n",
    "earthquakes.head(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cbe807a6-72e7-4a30-bdae-3f9da91657ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "earthquakes.hvplot.points('lon', 'lat', tiles=True, alpha=0.6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37b544b9-ee78-4288-8057-6fb8bb3af8c8",
   "metadata": {},
   "source": [
    "### With GeoViews\n",
    "\n",
    "For more advanced mapping features, you can optionally install [GeoViews](https://geoviews.org/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6fd193b0-8e12-4762-be0a-146d8c570b25",
   "metadata": {},
   "outputs": [],
   "source": [
    "import cartopy.crs as crs\n",
    "\n",
    "air_ds.hvplot.quadmesh(\n",
    "    'lon', 'lat', projection=crs.Orthographic(-90, 30), project=True,\n",
    "    global_extent=True, cmap='viridis', coastline=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9db9429-c88d-44dd-bf2b-2a220820d487",
   "metadata": {},
   "source": [
    "For more information, see the [User guide section](https://hvplot.holoviz.org/user_guide/Geographic_Data.html) on geographic plots"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c98e7228-889c-41ad-981b-174b890cab82",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Matplotlib or Plotly plots\n",
    "\n",
    "hvPlot offers the possibility to create [Matplotlib](https://matplotlib.org/) and [Plotly](https://plotly.com/) plots. Load and enable the chosen plotting library with the `extension` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c7970bc-66a2-445b-b7fe-7c88ce90141b",
   "metadata": {},
   "outputs": [],
   "source": [
    "hvplot.extension('matplotlib')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be6f5617-7517-4881-9db7-37a9085f7918",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_penguins.hvplot.scatter(x='bill_length_mm', y='bill_depth_mm', by='sex')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77b34a64-a3f8-468a-b263-0b186bff6f0b",
   "metadata": {},
   "source": [
    "## Rendering and saving output\n",
    "\n",
    "In notebook environments like Jupyter or VS Code, objects returned by hvPlot calls are displayed automatically. For example, this documentation page is built from a Jupyter notebook.\n",
    "\n",
    "If you’re running code outside of a notebook (e.g., in a Python script or console), you can:\n",
    "- Display plots: Use `hvplot.show(<obj>)` to render plots in a browser or interactive viewer.\n",
    "- Save plots: Use `hvplot.save(<obj>, 'this_plot.html')` to save plots to an HTML file (e.g., for Bokeh) for later viewing.\n",
    "\n",
    ":::{tip}\n",
    "When using Bokeh as the plotting backend, you can also save plots directly using the “Save” icon in the plot’s toolbar.\n",
    ":::\n",
    "\n",
    "For more information about viewing or saving plots, check out the user guide section on [viewing plots](https://hvplot.holoviz.org/user_guide/Viewing.html#)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "279962d9-c1f5-43ce-9fc1-0f517f562ea3",
   "metadata": {},
   "source": [
    "## hvPlot explorer\n",
    "\n",
    "The *Explorer* is a [Panel](https://panel.holoviz.org)-based web application with which you can easily explore your data. While using `.hvplot()` is a convenient way to create plots from data, it assumes some *a piori* knowledge about the data itself and its structure, and also knowledge about `.hvplot()`'s API itself. The *Explorer* is a graphical interface that offers a simple way to select and visualize the kind of plot you want to see your data with, and many options to customize that plot."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09ad8823-ba17-443e-bccc-82826240ffa7",
   "metadata": {},
   "source": [
    "### Set up\n",
    "\n",
    "Setting up the explorer is pretty simple in a notebook. You just need to make sure you have loaded the extension, either via a data type import (e.g. `import hvplot.pandas`) or directly (e.g. `hvplot.extension('bokeh')`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "512e7b44-f189-4e99-a7ee-7b15b72e8987",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "# not displayed on the site\n",
    "hvplot.output(backend='bokeh')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fdb3ae1-5864-4731-9d32-57324551103a",
   "metadata": {},
   "source": [
    "### Basic usage"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bc74294-7d1b-4644-8140-3b05913c5224",
   "metadata": {},
   "source": [
    "The explorer is available on the `.hvplot` namespace together with the other plotting methods. It accepts most of the parameters accepted by the `.hvplot()` API. For the purpose of producing a nice example on the documentation, we will instantiate an explorer with some pre-defined parameters; usually you would instantiate it without any parameter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "980f89ff-bc1e-40a7-9a78-960d275376f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "explorer = df_penguins.hvplot.explorer(x='bill_length_mm', y='bill_depth_mm', by=['species'])\n",
    "explorer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bdd3a303-c03f-4e2f-bfc4-d6a1c2d41ab5",
   "metadata": {
    "tags": []
   },
   "source": [
    "Spend some time browsing the explorer and the options it offers."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11bbbf82-12fe-4e74-89bd-6d4abd61a7dc",
   "metadata": {
    "tags": []
   },
   "source": [
    ":::{note}\n",
    "This interactive functionality requires a live Python process to be running.\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc774dd0-8609-4ef9-a97a-1e14439bb5e0",
   "metadata": {
    "tags": []
   },
   "source": [
    "Once you are done exploring the data you may want to record the settings you have configured or save the plot. The easiest option consists of opening the *Code* tab next to *Plot* and copy/pasting the code displayed in a new notebook cell, executing it will generate exactly the same code as seen in the explorer."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8dbb2796-7658-45e3-9335-f0d55f2ba084",
   "metadata": {
    "tags": []
   },
   "source": [
    "## hvPlot interactive\n",
    "\n",
    "hvPlot isn't only a plotting library, it is dedicated to making data exploration easier. The `hvplot.interactive()` API can help you to get better control over your data pipelines. We define a *data pipeline* as a series of commands that *transform* some data, such as aggregating, filtering, reshaping, renaming, etc. A data pipeline may include a *load* step that will provide the input data to the pipeline, e.g. reading the data from a database. \n",
    "\n",
    "When you analyze some data in a notebook that is for instance held in a Pandas DataFrame, you may find yourself having to re-run many cells after changing the parameters you provide to Pandas' methods, either to get more insights on the data or fine-tune an algorithm. `.interactive()` is a solution to improve this rather cumbersome workflow, by which you replace the constant parameters in the pipeline by widgets (e.g. a number slider), that will automatically get displayed next to your pipeline output and will trigger an output update on changes. With this approach all your pipeline parameters are available in one place and you get full interactive control over the pipeline.\n",
    "\n",
    "`.interactive()` doesn't only work with DataFrames but also with Xarray data structures, this is what we are going to show in this guide. First we will import `hvplot.xarray` which is going to make available the `.interactive()` accessor on Xarray objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f12005e-a145-4732-84b3-a0bf7c0b8cee",
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.xarray  # noqa"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38bbbbd3-37e0-4bb3-beab-f5953e13a7ce",
   "metadata": {},
   "source": [
    "We load the `air_temperature` dataset and get a handle on its unique *air* variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22c4d88c-72e3-4e38-b479-84842ce4ebb1",
   "metadata": {},
   "outputs": [],
   "source": [
    "air = air_ds.air\n",
    "air"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81b64fc0-660b-4bf6-b233-b7398a4d50aa",
   "metadata": {},
   "source": [
    "We want to better understand the temporal evolution of the air temperature over different latitudes compared to a baseline. The data pipeline we build includes:\n",
    "\n",
    "1. filtering the data at one latitude\n",
    "2. cleaning up the data\n",
    "3. aggregating the temperatures by time\n",
    "4. computing a rolling mean\n",
    "5. subtracting a baseline from the above\n",
    "\n",
    "The output we choose for now is the `.describe()` method of Pandas. This pipeline has two parameters, the latitude and the temporal window of the rolling operation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "53709c6f-876b-4489-a014-f5c0d49f515d",
   "metadata": {},
   "outputs": [],
   "source": [
    "LATITUDE = 30.\n",
    "ROLLING_WINDOW = '1D'\n",
    "\n",
    "baseline = air.sel(lat=LATITUDE).mean().item()\n",
    "pipeline = (\n",
    "    air\n",
    "    .sel(lat=LATITUDE)\n",
    "    .to_dataframe()\n",
    "    .drop(columns='lat')\n",
    "    .groupby('time').mean()\n",
    "    .rolling(ROLLING_WINDOW).mean()\n",
    "    - baseline\n",
    ")\n",
    "pipeline.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c06ec25-0563-4190-812b-38bb9185de70",
   "metadata": {},
   "source": [
    "Without using `.interactive()`, we would need to manually change the values of `LATITUDE` and `ROLLING_WINDOW` to observe how they affect the pipeline’s output. Instead, we can create two widgets that represent the range of values we expect these parameters to take. Essentially, this allows us to define our parameter space in advance. To create the widgets, we import [Panel](https://panel.holoviz.org) and select two appropriate widgets from its [Reference Gallery](https://panel.holoviz.org/reference/index.html#widgets)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a35b33cb-7669-4128-8e1e-c57281a0cc55",
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "\n",
    "w_latitude = pn.widgets.DiscreteSlider(name='Latitude', options=list(air.lat.values))\n",
    "w_rolling_window = pn.widgets.RadioButtonGroup(name='Rolling window', options=['1D', '7D', '30D'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7165df5b-b307-4fd4-ac30-41b7d0ce8051",
   "metadata": {},
   "source": [
    "Now we instantiate an *Interactive* object by calling `.interactive()` on our data. This object mirrors the underlying object API, accepting all of its natural operations. We replace the data by the interactive object in the pipeline, and replace the constant parameters by the widgets we have just created."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a620f0a-5cc0-45fa-bb74-7a8b82c08d4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "airi = air.interactive()\n",
    "baseline = airi.sel(lat=w_latitude).mean().item()\n",
    "pipeline = (\n",
    "    airi\n",
    "    .sel(lat=w_latitude)\n",
    "    .to_dataframe()\n",
    "    .drop(columns='lat')\n",
    "    .groupby('time').mean()\n",
    "    .rolling(w_rolling_window).mean()\n",
    "    - baseline\n",
    ")\n",
    "pipeline.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5f56064-2a13-4c72-b77d-5ad64626bbd0",
   "metadata": {},
   "source": [
    "You can see that now the pipeline when rendered doesn't only consist of its output, it also includes the widgets that control it. Change the widgets' values and observe how the output dynamically updates.\n",
    "\n",
    ":::{note}\n",
    "This interactive functionality requires a live Python process to be running.\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65d19ba2-2161-4432-82ed-b9cb6e84ea6e",
   "metadata": {},
   "source": [
    "You can notice that `.interactive()` supports the fact that the data type changed in the pipeline (see the call to `.to_dataframe`) and that it also supports math operators (`- baseline`).\n",
    "\n",
    "A plot would be a better output for this pipeline. We will use `.hvplot()` to create an interactive Bokeh line plot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c29a9aa-0a51-4dc6-8bf6-12dade9d15ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "pipeline.hvplot(height=300, responsive=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3c09926-9215-4c7a-9f69-94b5a9675643",
   "metadata": {
    "tags": []
   },
   "source": [
    ":::{note}\n",
    "This interactive functionality requires a live Python process to be running.\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1b76cc4-81fc-4e9b-8af2-53b6ddc751eb",
   "metadata": {
    "tags": []
   },
   "source": [
    "For more information about the various hvPlot capabilities, take a look at the [User Guide](https://hvplot.holoviz.org/user_guide/index.html)."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
